/**
 * 
 */
package co.fitstart.admin.dao;

import java.util.List;
import com.demo2do.core.persistence.annotation.Dynamic;
import com.demo2do.core.persistence.annotation.Execute;
import com.demo2do.core.persistence.annotation.Limit;
import com.demo2do.core.persistence.annotation.Query;
import com.demo2do.core.persistence.annotation.Variable;
import co.fitstart.entity.course.Course;
import co.fitstart.entity.course.CourseType;
import co.fitstart.entity.course.CourseUnit;
import co.fitstart.entity.finance.InventoryExportRecord;
import co.fitstart.entity.product.Product;
import co.fitstart.entity.product.ProductType;
import co.fitstart.entity.product.Status;
import co.fitstart.entity.product.stat.UserProductBehavior;

/**
 * @author downpour
 *
 */
@Dynamic("hibernate")
public interface ProductDao {
    
    /**
     * 
     * @param export
     * @param beginIndex
     * @param maxResult
     * @return
     */
    @Limit
    @Query("FROM Product product WHERE product.course.group = false AND export = :export ORDER BY createTime DESC")
    public List<Product> list(@Variable("export") boolean export, @Variable("beginIndex") int beginIndex, @Variable("maxResult") int maxResult);
    
    /**
     * 
     * @return
     */
    @Query("FROM Product product WHERE export = false ORDER BY createTime DESC")
    public List<Product> listUnExportProduct();
    
    
    /**
     * list products by page
     * 
     * @param type
     * @param beginIndex
     * @param maxResult
     * @return
     */
    @Limit
    @Query("FROM Product product WHERE product.deleted = false AND product.disabled = false AND product.type = :type ORDER BY product.weight DESC, createTime DESC")
    public List<Product> list(@Variable("type")ProductType type, @Variable("beginIndex") int beginIndex, @Variable("maxResult") int maxResult);
    
    /**
     * list sticky product
     * 
     * @param type
     * @return
     */
    @Query("FROM Product product WHERE product.disabled = false AND product.type = :type AND product.weight > 100  ORDER BY product.weight ASC")
    public List<Product> list(@Variable("type")ProductType type);
    
    /**
     * load latest product
     * 
     * @param course
     * @return
     */
    @Query("FROM Product product WHERE product.disabled = false AND product.course = :course ORDER BY product.createTime DESC")
    public Product loadLatestProduct(@Variable("course")Course course);
    
    /**
     * 
     * @param product
     * @param tagsToDelete
     */
    @Execute("DELETE FROM ProductTag productTag WHERE productTag.product = :product AND productTag.id in (:tagIds)")
    public void deleteProductTags(@Variable("product") Product product, @Variable("tagIds") List<Long> tagsToDelete);
    
    /**
     * load user product behavior by product and openid
     * 
     * @param product
     * @param openid
     * @return
     */
    @Query("FROM UserProductBehavior userProductBehavior WHERE userProductBehavior.openid = :openid AND userProductBehavior.product = :product")
    public UserProductBehavior loadUserProductBehavior(@Variable("product")Product product, @Variable("openid")String openid);
    
    /**
     * 
     * @param productIds
     */
    @Execute("UPDATE Product SET export = true WHERE id in (:productIds)")
    public void exportInventories(@Variable("productIds") List<Long> productIds);
    
    @Limit
    @Query("FROM InventoryExportRecord ORDER BY createTime DESC")
    public List<InventoryExportRecord> listExportRecord(@Variable("beginIndex") int beginIndex, @Variable("maxResult") int maxResult);
    
    /**
     * 
     * @param status
     * @return
     */
    @Query("FROM Product WHERE disabled = false AND course.give = true AND status = :status AND buyable = true")
    public List<Product> listGive(@Variable("status") Status status);
    
    /**
     * 
     * @param status
     * @return
     */
    @Query("FROM Product WHERE disabled = false AND course.experience = true AND status = :status AND buyable = true")
    public List<Product> listExperience(@Variable("status") Status status);
    
    /**
     * 
     * @param status
     * @return
     */
    @Query("FROM Product WHERE id = :productId")
    public Product load(@Variable("productId") Long productId);

    @Query("FROM Product WHERE disabled = false AND course.hours = :hours AND buyable = true AND name LIKE :name")
    //@Query("from Product where disabled = false and course.give = true and buyable = true")
    public List<Product> ifExist(@Variable("hours") int hours, @Variable("name") String name);

    @Query("FROM Product WHERE disabled = false AND buyable = true AND name LIKE :name")
    //@Query("from Product where disabled = false and course.give = true and buyable = true")
    public List<Product> ifExist(@Variable("name") String name);

    @Query("FROM Product WHERE disabled = false AND course.hours = :hours AND buyable = true")
    public Product getProduct(@Variable("hours") int hours);

    @Query("FROM Product WHERE disabled = false AND course.hours = :hours AND buyable = true AND name LIKE :name")
    public Product getProduct(@Variable("hours") int hours, @Variable("name") String name);
    
    /**
     * 
     * @param courseType
     * @param courseUnit
     * @return
     */
    @Query("FROM Product WHERE disabled = false AND course.courseType = :courseType AND buyable = true AND courseUnit = :courseUnit")
    public Product getProduct(@Variable("courseType") CourseType courseType, @Variable("courseUnit") CourseUnit courseUnit);
    
    @Query("FROM Product WHERE disabled = false AND course.hours = :hours AND buyable = true AND courseUnit = :courseUnit")
    public Product getProduct(@Variable("hours") int hours, @Variable("courseUnit") CourseUnit courseUnit);

    @Query("FROM Product WHERE disabled = false AND buyable = true AND name LIKE :name")
    public Product getProduct(@Variable("name") String name);
}
